Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose onchain transactions in store #432

Merged

Conversation

tnull
Copy link
Collaborator

@tnull tnull commented Jan 16, 2025

Closes #67

Previously, onchain-transactions where not tracked in our PaymentStore.
Now, that the upgrade to BDK 1.0 is behind us, we take a stab at finally exposing them in our interface via PaymentStore.

In the future we're looking to add dedicated PaymentKinds for channel fundings/channel closes (see #447), but for now all are exposed under the Onchain umbrella kind.

@tnull tnull marked this pull request as draft January 16, 2025 13:28
@tnull tnull added this to the 0.5 milestone Jan 16, 2025
@tnull tnull mentioned this pull request Jan 23, 2025
10 tasks
@tnull tnull force-pushed the 2025-01-include-onchain-transactions-in-store branch 2 times, most recently from b959830 to 306a78e Compare January 27, 2025 15:45
@tnull tnull changed the title Expose onchain transactions in store and events Expose onchain transactions in store Jan 27, 2025
@tnull
Copy link
Collaborator Author

tnull commented Jan 27, 2025

As we currently don't have a good wait to discern closing transactions, I now split out the event emission to #448 which will land at a later date. Going ahead and undrafting this.

@tnull tnull marked this pull request as ready for review January 27, 2025 15:57
@tnull tnull force-pushed the 2025-01-include-onchain-transactions-in-store branch 2 times, most recently from 585e14f to 6437515 Compare January 27, 2025 16:45
@tnull tnull requested a review from jkczyz January 27, 2025 16:46
@tnull tnull force-pushed the 2025-01-include-onchain-transactions-in-store branch from 6437515 to 403be03 Compare January 27, 2025 17:03
Comment on lines +177 to +188
// TODO: It would be great to introduce additional variants for
// `ChannelFunding` and `ChannelClosing`. For the former, we could just
// take a reference to `ChannelManager` here and check against
// `list_channels`. But for the latter the best approach is much less
// clear: for force-closes/HTLC spends we should be good querying
// `OutputSweeper::tracked_spendable_outputs`, but regular channel closes
// (i.e., `SpendableOutputDescriptor::StaticOutput` variants) are directly
// spent to a wallet address. The only solution I can come up with is to
// create and persist a list of 'static pending outputs' that we could use
// here to determine the `PaymentKind`, but that's not really satisfactory, so
// we're punting on it until we can come up with a better solution.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this gets more complicated with splicing in/out or more exotic transactions paying us and opening a channel, for instance.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, good point, now opened the more lightningdevkit/rust-lightning#3566 to supersede lightningdevkit/rust-lightning#3548

Would be great if an API allowing to query the type of a given transaction (Txid) could be added as part of the splicing work.

Comment on lines +190 to +199
let (direction, amount_msat) = if sent > received {
let direction = PaymentDirection::Outbound;
let amount_msat = Some(sent.to_sat().saturating_sub(received.to_sat()) * 1000);
(direction, amount_msat)
} else {
let direction = PaymentDirection::Inbound;
let amount_msat = Some(received.to_sat().saturating_sub(sent.to_sat()) * 1000);
(direction, amount_msat)
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we consider these two separate payments? I guess we could't use the txid as the payment id, though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mhh, given that (IIUC) received includes the change, I'd rather not add each change output as an inbound payment?

Comment on lines +160 to +166
let payment_status = if cur_height >= confirmation_height + ANTI_REORG_DELAY - 1
{
PaymentStatus::Succeeded
} else {
PaymentStatus::Pending
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Say the transaction was re-orged out and was then RBF'ed. Is that possible? Would we have payment stuck in pending?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, that's a very valid concern. Tbh. I'm not entirely sure how to handle that: for one, the RBF'd transaction is technically pending as there could be another reorg that makes it part of the best chain again. So essentially any signed & broadcasted transaction remains 'pending' forever.

I think the only way I can come up with to handle this would be to never add Pending transactions but jump to Succeeded directly once they reach ANTI_REORG_DELAY. Or we just keep the current approach and add docs noting that transactions in pending might never succeed for one reason or another?

I think at least for BDK's own RBF's we could see if we find a better solution when we do #367.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we possibly detect that the UTXO has been spent and remove the pending payment?

Copy link
Collaborator Author

@tnull tnull Jan 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess, but that would require us to keep track and persist a list of all the UTXOs, write an adapter around lightning-transaction-sync's Filter implementation to also register spends for them, and then implement Confirm on Wallet, just to be able to remove any Pending entries that have been replaced.

For now that seems like a lot of overhead to just account for this rare edgecase (reorg + RBF)? But I wouldn't completely rule it out to do something like it in if we find we need to do additional RBF tracking anyways as part of #367.

// here to determine the `PaymentKind`, but that's not really satisfactory, so
// we're punting on it until we can come up with a better solution.
let kind = crate::payment::PaymentKind::Onchain { txid, status: confirmation_status };
let (sent, received) = locked_wallet.sent_and_received(&wtx.tx_node.tx);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is change abstracted away from this API?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, the docs state:

    /// This method returns a tuple `(sent, received)`. Sent is the sum of the txin amounts
    /// that spend from previous txouts tracked by this wallet. Received is the summation
    /// of this tx's outputs that send to script pubkeys tracked by this wallet.

so IIUC received would include the change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't the change be more than the amount sent, making it look like an inbound payment when it was really an outbound? Or am I misunderstanding?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't the change be more than the amount sent, making it look like an inbound payment when it was really an outbound? Or am I misunderstanding?

IIUC, any change amount would be accounted for both in sent and received, so you can essentially ignore it in terms of comparisons (think: subtract on both sides).

Say you send a payment of 10 sats, and add a txin spending an wallet output with 100 sats. This would result in two txouts, one to the recipient with 10 sats, one change back to a wallet address with 85sats or so, leaving 5 for mining fees. IIUC, this would result in sent = 100, received = 85, resulting in sent > received => PaymentDirection::Outbound.

@tnull tnull force-pushed the 2025-01-include-onchain-transactions-in-store branch 2 times, most recently from 1d05f9c to 993bf0b Compare January 28, 2025 10:50
Copy link
Contributor

@jkczyz jkczyz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel free to squash

Comment on lines +160 to +166
let payment_status = if cur_height >= confirmation_height + ANTI_REORG_DELAY - 1
{
PaymentStatus::Succeeded
} else {
PaymentStatus::Pending
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we possibly detect that the UTXO has been spent and remove the pending payment?

tnull added 3 commits January 30, 2025 13:55
Here, we move updating fields via `PaymentDetailsUpdate` to
`PaymentDetails::update`. This allows us to only update the fields that
changed, keeping track *whether* something changed, and only updating
the timestamp and persisting the entry *if* something changed.

This is a nice improvement in general (as we want to reduce persist
calls anyways), but we'll also use this for batch updates in the next
commits.
We implement an inserting/updating method that will only persist entries that
have been changed.
@tnull tnull force-pushed the 2025-01-include-onchain-transactions-in-store branch from 993bf0b to da45da3 Compare January 30, 2025 12:56
@tnull
Copy link
Collaborator Author

tnull commented Jan 30, 2025

Rebased to resolve minor conflicts

tnull added 3 commits January 30, 2025 17:03
Previously, `PaymentKind::Onchain` was simply a placeholder entry we
never actually used. Here, we extend it to include fields that are
actually useful.
We update the payment store whenever syncing the wallet state finished.
@tnull tnull force-pushed the 2025-01-include-onchain-transactions-in-store branch from da45da3 to 0710434 Compare January 30, 2025 16:03
@tnull
Copy link
Collaborator Author

tnull commented Jan 30, 2025

Squashed the fixup without further changes.

@tnull tnull merged commit aaf74cc into lightningdevkit:main Jan 30, 2025
5 of 14 checks passed
@danielnordh
Copy link

Yes, thank you for getting this done!!

@reez reez mentioned this pull request Feb 3, 2025
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Expose on-chain transactions
3 participants